package cn.zye.net;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import android.util.Log;

public class ping {
	private final static String LOG_TAG = "NetworkTools";
	private final static int PING_TIMEOUT = 3000;
	private final static int PING_COUNT = 1;
	private final static int PING_DEFAULT_PORT = 80;
	final static String ls = "<br />";

	public static boolean start(String host, String port) {
		String s = JavaPing(host, port)[0];
		if ("Unknown,n/a".contains(s)) {
			return false;
		}
		return true;
	}

	public static String[] JavaPing(String host, String portString) {
		final int timeout = PING_TIMEOUT;
		final int count = PING_COUNT;

		int port = PING_DEFAULT_PORT;
		String netstate = "";
		String mResult = "Pinging " + host + " using TCP on port " + port + ls;
		try {
			int p = Integer.parseInt(portString);
			port = p;
		} catch (NumberFormatException e) {
			Log.v(LOG_TAG, "Number format exception - using default port "
					+ PING_DEFAULT_PORT);
			mResult += portString + " is not a number, using default port "
					+ PING_DEFAULT_PORT + ls;
		}

		InetAddress address = null;
		try {
			address = InetAddress.getByName(host);
		} catch (UnknownHostException e) {
			mResult += "Unknown host " + host + ls;
			netstate = "Unknown";
			return new String[] { netstate, mResult };
		}

		long[] rtt = new long[count];
		for (int i = 0; i < count; i++) {

			Socket s = new Socket(); // Could maybe re-use this

			try {
				s.bind(null);
			} catch (IOException e) {
				mResult += "Unknown host " + host + ls;
				netstate = "Unknown";
				return new String[] { netstate, mResult };
			}

			String state = "n/a";
			netstate = "n/a";
			String reachable = "unreachable";
			long t = 0;
			long start = System.currentTimeMillis();
			try {
				s.connect(new InetSocketAddress(address, port), timeout);
				t = System.currentTimeMillis() - start;
				s.close();
				reachable = "reachable";
				state = "open";
				netstate = "open";
			} catch (SocketTimeoutException e) {
				Log.v(LOG_TAG, "SocketTimeoutException " + e.toString());
			} catch (IOException e) {
				if (e.toString().matches(".*Connection refused.*")) {
					t = System.currentTimeMillis() - start;
					Log.v(LOG_TAG, "IOException " + e.toString()
							+ " is a successfull ping");
					state = "closed";
					netstate = "closed";
					reachable = "reachable";
				}
			}
			rtt[i] = t;
			mResult += (i + 1) + ": " + reachable + " on port " + port + "("
					+ state + ")" + " in " + t + "ms" + ls;
			if (count > 1) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					Log.e(LOG_TAG,
							"InterruptedException (unable to sleep)"
									+ e.toString());
				}
			}
			if(s.isConnected()){
				try {
					s.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		long max = 0;
		long min = -1;
		long total = 0;
		int returned = 0;
		for (int i = 0; i < count; i++) {
			if (rtt[i] > 0) {
				returned++;
				if (min > rtt[i] || min == -1) {
					min = rtt[i];
				}
				if (max < rtt[i]) {
					max = rtt[i];
				}
				total += rtt[i];
			}
		}
		long ave = returned > 0 ? total / returned : 0;
		min = min < 0 ? 0 : min;
		mResult += "Min: " + Tools.insertCommas(String.valueOf(min))
				+ ", Max: " + Tools.insertCommas(String.valueOf(max))
				+ ", Ave: " + Tools.insertCommas(String.valueOf(ave)) + ls;
		return new String[] { netstate, mResult };
	}
}
